package com.emm.yixun.basic.service.impl;

import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.emm.yixun.basic.mapper.RoleDataAuthorityMapper;
import com.emm.yixun.basic.mapper.RoleMapper;
import com.emm.yixun.basic.mapper.SalesGroupMapper;
import com.emm.yixun.basic.mapper.SalesGroupUserMapper;
import com.emm.yixun.basic.mapper.UserMapper;
import com.emm.yixun.basic.service.DataPermissionService;
import com.emm.yixun.basic.service.DepartmentService;
import com.emm.yixun.common.enums.DataAuthorityEnums;
import com.emm.yixun.common.model.Department;
import com.emm.yixun.common.model.Role;
import com.emm.yixun.common.model.RoleDataAuthority;
import com.emm.yixun.common.model.SalesGroup;
import com.emm.yixun.common.model.SalesGroupUser;
import com.emm.yixun.common.model.User;
import com.emm.yixun.common.model.dto.DepartmentDto;
import com.emm.yixun.common.model.dto.RoleDataAuthorityDto;
import com.emm.yixun.common.model.dto.SalesGroupUserDto;
import com.emm.yixun.common.model.enums.DelFlagEnum;
import com.emm.yixun.common.model.enums.UserStatusEnum;

@Service("dataPermissionService")
public class DataPermissionServiceImpl implements DataPermissionService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private SalesGroupUserMapper salesGroupUserMapper;

    @Autowired
    private SalesGroupMapper salesGroupMapper;

    @Autowired
    private RoleDataAuthorityMapper roleDataAuthorityMapper;

    @Autowired
    private DepartmentService departmentService;

    private static String SHIRO_ALL = "0001";

    public String roleDataAuthorityValue(Long userId, String resourcesCode) {
        User user = userMapper.selectById(userId);
        //判断是不是admin
        if ("1".equals(user.getIsAdmin())) {
            return DataAuthorityEnums.DATA_AUTHORITY_99.getNo();
        }
        if (null == user || UserStatusEnum.UN_USE.getNo().equals(user.getUserStatus())
                || DelFlagEnum.DEL.getNo().equals(user.getDelFlag())) {
            return DataAuthorityEnums.DATA_AUTHORITY_00.getNo();
        }
        long roleId = user.getRoleId();
        RoleDataAuthorityDto rdahDto = new RoleDataAuthorityDto();
        rdahDto.setResourcesCode(resourcesCode);
        rdahDto.setRoleId(roleId);
        rdahDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
        rdahDto.setOrders("create_time desc");
        List<RoleDataAuthority> rdahList = roleDataAuthorityMapper.selectListByDto(rdahDto);
        if (null == rdahList || rdahList.size() == 0) {
            return DataAuthorityEnums.DATA_AUTHORITY_00.getNo();
        }
        RoleDataAuthority rdah = rdahList.get(0);
        return rdah.getAuthorityValue();
    }

    public String dataPermissionCondition(Long userId, String resourcesCode, String prefix, String columnName) {
        // 默认返回无权限字符
        String condition = "00: and 1=2 ";
        // 无用户、无资源,不做数据权限控制
        // 暂时以此方案处理,后期可能会修改
        if (null == userId || StringUtils.isEmpty(resourcesCode)) {
            condition = "99: and 1=1 ";
            return condition;
        }

        String resourcesCodeArr[] = resourcesCode.split("[,]");
        if (resourcesCodeArr.length > 0) {
            StringBuffer sbCondition = new StringBuffer();
            sbCondition.append("88: ");
            for (int ii = 0; ii < resourcesCodeArr.length; ii++) {
                String resCode = resourcesCodeArr[ii];
                if (StringUtils.isNotEmpty(resCode)) {
                    // 1、根据userId,获取员工信息
                    // 1.1、员工不存在、被删除、不可用状态,返回无权限
                    User user = userMapper.selectById(userId);
                    if (null == user || UserStatusEnum.UN_USE.getNo().equals(user.getUserStatus())
                            || DelFlagEnum.DEL.getNo().equals(user.getDelFlag())) {
                        continue;
                    }
                    // 1.2、判断是不是admin
                    if ("1".equals(user.getIsAdmin())) {
                        condition = "99: and 1=1";
                        String[] conditionArr = condition.split(":");
                        String conditionContent = conditionArr[1];
                        sbCondition.append(conditionContent);
                        sbCondition.append(" ");
                        continue;
                    }

                    long roleId = user.getRoleId();

                    // 2、根据角色,获取用户角色资源权限 sys_tr_role_data_authority
                    RoleDataAuthorityDto rdahDto = new RoleDataAuthorityDto();
                    rdahDto.setResourcesCode(resCode);
                    rdahDto.setRoleId(roleId);
                    rdahDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
                    rdahDto.setOrders("create_time desc");
                    List<RoleDataAuthority> rdahList = roleDataAuthorityMapper.selectListByDto(rdahDto);
                    if (null == rdahList || rdahList.size() == 0) {
                        continue;
                    }

                    // 用户项目组Map
                    Map<Long, String> sgUserMap = new HashMap<Long, String>();
                    // 用户销售组set
                    Set<String> salesSet = new HashSet<String>();
                    RoleDataAuthority rdah = rdahList.get(0);
                    if (DataAuthorityEnums.DATA_AUTHORITY_99.getNo().equals(rdah.getAuthorityValue())) {
                        // 拥有全部权限
                        condition = "99: and 1=1";
                        String[] conditionArr = condition.split(":");
                        String conditionContent = conditionArr[1];
                        sbCondition.append(conditionContent);
                        sbCondition.append(" ");
                        continue;
                    } else if (DataAuthorityEnums.DATA_AUTHORITY_00.getNo().equals(rdah.getAuthorityValue())) {
                        // 拥有全部权限
                        condition = "00: and 1=2";
                        String[] conditionArr = condition.split(":");
                        String conditionContent = conditionArr[1];
                        sbCondition.append(conditionContent);
                        sbCondition.append(" ");
                        continue;
                    } else if (DataAuthorityEnums.DATA_AUTHORITY_02.getNo().equals(rdah.getAuthorityValue())) {
                        // 3、根据userId,获取员工角色对应的权限 sys_tm_role
                        // 3.1、角色不存在或被删除,返回无权限
                        Role role = roleMapper.selectById(roleId);
                        if (null == role || DelFlagEnum.DEL.getNo().equals(role.getDelFlag())) {
                            continue;
                        }

                        SalesGroupUserDto salesGroupUserDto = new SalesGroupUserDto();
                        salesGroupUserDto.setUserId(userId);
                        salesGroupUserDto.setStatus("0");
                        List<SalesGroupUser> salesGroupUserList = salesGroupUserMapper.selectListByDto(salesGroupUserDto);
                        if (null == salesGroupUserList || salesGroupUserList.size() == 0) {
                            sbCondition.append(" AND 1=2");
                            continue;
                        }

                        // 销售组Map
                        for (SalesGroupUser salesGroupUser : salesGroupUserList) {
                            SalesGroup salesGroup = salesGroupMapper.selectById(salesGroupUser.getSalesGroupId());
                            if (null == salesGroup)
                                continue;
                            sgUserMap.put(salesGroup.getId(), salesGroup.getProjectCode());
                        }
                    } else if (DataAuthorityEnums.DATA_AUTHORITY_04.getNo().equals(rdah.getAuthorityValue())) {
//						Role role = roleMapper.selectById(roleId);
//						if (null == role || DelFlagEnum.DEL.getNo().equals(role.getDelFlag())) {
//							continue;
//						}
//
//						salesSet = salesGroupUserMapper.selectUsercodeListByOneOfGroupUserId(userId);
//						if (null == salesSet || salesSet.size() == 0){
//							sbCondition.append(" AND 1=2");
//							continue;
//						}
                        prefix = prefix == null?"t":prefix;
                        String sql = "and " + prefix + ".user_code IN (\n" +
                                "\tSELECT DISTINCT\n" +
                                "\t\tuser_code\n" +
                                "\tFROM\n" +
                                "\t\tsys_tm_user\n" +
                                "\tWHERE\n" +
                                "\t\tid IN (\n" +
                                "\t\t\tSELECT DISTINCT\n" +
                                "\t\t\t\tuser_id\n" +
                                "\t\t\tFROM\n" +
                                "\t\t\t\tmkt_tr_sales_group_user\n" +
                                "\t\t\tWHERE\n" +
                                "\t\t\t\tsales_group_id IN (\n" +
                                "\t\t\t\t\tSELECT DISTINCT\n" +
                                "\t\t\t\t\t\tsales_group_id\n" +
                                "\t\t\t\t\tFROM\n" +
                                "\t\t\t\t\t\tmkt_tr_sales_group_user\n" +
                                "\t\t\t\t\tWHERE\n" +
                                "\t\t\t\t\t\tuser_id = "+userId+"\n" +
                                "\t\t\t\t\tAND del_flag = '0'\n" +
                                "\t\t\t\t\tAND access_code = (\n" +
                                "\t\t\t\t\t\tSELECT\n" +
                                "\t\t\t\t\t\t\tproject_code\n" +
                                "\t\t\t\t\t\tFROM\n" +
                                "\t\t\t\t\t\t\tpro_tm_project\n" +
                                "\t\t\t\t\t\tWHERE\n" +
                                "\t\t\t\t\t\t\tid = " + prefix + ".project_id\n" +
                                "\t\t\t\t\t)\n" +
                                "\t\t\t\t\tAND STATUS = 0\n" +
                                "\t\t\t\t)\n" +
                                "\t\t\tAND del_flag = '0'\n" +
                                "\t\t\tAND STATUS = 0\n" +
                                "\t\t)\n" +
                                "\tAND del_flag = '0'\n" +
                                ")";
                        sbCondition.append(sql);
                        sbCondition.append(" ");
                        continue;
                    }
                    condition = buildCondition(user, sgUserMap, salesSet, rdah, prefix, columnName) + " ";
                    String[] conditionArr = condition.split(":");
                    String conditionContent = conditionArr[1];
                    sbCondition.append(conditionContent);
                    sbCondition.append(" ");
                }
            }
            condition = sbCondition.toString();
        }

        return condition;
    }

    /**
     * 创建用户权限信息
     *
     * @param user      用户
     * @param sgUserMap 用户销售组,产品权限信息
     * @param rdah      用户角色数据权限
     * @return
     */
    public String buildCondition(User user, Map<Long, String> sgUserMap, Set<String> sgMap, RoleDataAuthority rdah,
                                 String prefix, String columnName) {
        String condition = "00: and 1=2 ";
        // 权限值,对应枚举类: DataAuthorityEnums
        String authorityValue = rdah.getAuthorityValue();
        // 表别名,默认为 t
        if (null == prefix) {
            prefix = "t";
        }
        if (null == columnName) {
            if (DataAuthorityEnums.DATA_AUTHORITY_01.getNo().equals(authorityValue)) {
                // 个人
                columnName = "user_code";
            } else if (DataAuthorityEnums.DATA_AUTHORITY_02.getNo().equals(authorityValue)) {
                // 销售组
                columnName = "access_code";
            } else if (DataAuthorityEnums.DATA_AUTHORITY_03.getNo().equals(authorityValue)) {
                // 本部,部门查询,权限向下
                columnName = "permission_code";
            } else if (DataAuthorityEnums.DATA_AUTHORITY_04.getNo().equals(rdah.getAuthorityValue())) {
                columnName = "user_code";
            } else if (DataAuthorityEnums.DATA_AUTHORITY_05.getNo().equals(rdah.getAuthorityValue())) {
                columnName = "user_id";
            }
        }

        if (DataAuthorityEnums.DATA_AUTHORITY_01.getNo().equals(authorityValue)) {
            // 个人code
            return buildUserCondition(user, prefix, columnName);
        } else if (DataAuthorityEnums.DATA_AUTHORITY_02.getNo().equals(authorityValue)) {
            // 项目组
            return buildpgCondition(sgUserMap, prefix, columnName);
        } else if (DataAuthorityEnums.DATA_AUTHORITY_03.getNo().equals(authorityValue)) {
            // 本部
            return buildDeptCondition(user, prefix, columnName);
        } else if (DataAuthorityEnums.DATA_AUTHORITY_04.getNo().equals(rdah.getAuthorityValue())) {
            // 销售组
            return buildSgCondition(sgMap, prefix, columnName);
        } else if (DataAuthorityEnums.DATA_AUTHORITY_05.getNo().equals(rdah.getAuthorityValue())) {
            // 个人id
            return buildUserIdCondition(user, prefix, columnName);
        }
        return condition;
    }

    /**
     * 创建个人权限过滤条件
     *
     * @return
     */
    public static String buildUserIdCondition(User user, String prefix, String columnName) {
        String condition = "";
        condition = "01: AND (" + prefix + "." + columnName + " = '" + user.getId() + "')";
        return condition;
    }

    /**
     * 创建个人权限过滤条件
     *
     * @return
     */
    public static String buildUserCondition(User user, String prefix, String columnName) {
        String condition = "";
        condition = "01: AND (" + prefix + "." + columnName + " = '" + user.getUserCode() + "')";
        return condition;
    }

    /**
     * 创建项目组权限过滤条件
     *
     * @return
     */
    public static String buildpgCondition(Map<Long, String> sgUserMap, String prefix, String columnName) {
        StringBuffer sb = new StringBuffer();
        sb.append("02: AND (");
        Iterator<Map.Entry<Long, String>> it = sgUserMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Long, String> entry = it.next();
            // 销售组,value值为产品编码 projectCode
            String value = entry.getValue();
            sb.append(prefix + "." + columnName + " = '" + value + "'");
            if (it.hasNext()) {
                sb.append(" or ");
            }
        }
        sb.append(")");
        return sb.toString();
    }

    /**
     * 创建本部权限过滤条件
     *
     * @return
     */
    public String buildDeptCondition(User user, String prefix, String columnName) {
        String condition = "00: and 1=2 ";
        // 机构权限字段: permission_code
        DepartmentDto deptDto = new DepartmentDto();
        deptDto.setId(user.getUserDepartmentId());
        Department department = departmentService.selectByDto(deptDto);
        if (null != department && null != department.getPermissionCode()) {
            condition = "03: AND (" + prefix + "." + columnName + " like '%" + department.getPermissionCode() + "%')";
        }
        return condition;
    }

    /**
     * 创建销售组权限过滤条件
     *
     * @return
     */
    public static String buildSgCondition(Set<String> sgMap, String prefix, String columnName) {
        StringBuffer sb = new StringBuffer();
        sb.append("04: AND (");
        Iterator<String> it = sgMap.iterator();
        while (it.hasNext()) {
            String value = it.next();
            sb.append(prefix + "." + columnName + " = '" + value + "'");
            if (it.hasNext()) {
                sb.append(" or ");
            }
        }
        sb.append(")");
        return sb.toString();
    }

    /*
     * (non-Javadoc)
     *
     * @see com.emm.yixun.basic.service.DataPermissionService#findReportShiro(java.lang.Long, java.lang.String)
     */
    public Map<String, Object> findReportShiro(Long userId, String resourcesCode) {
        Map<String, Object> map = new HashMap<String, Object>();
        // 1、根据userId,获取员工信息
        // 1.1、员工不存在、被删除、不可用状态,返回无权限
        User user = userMapper.selectById(userId);
        // 1.2、判断是不是admin
        if ("1".equals(user.getIsAdmin())) {
            return null;
        }
        if (null == user || UserStatusEnum.UN_USE.getNo().equals(user.getUserStatus())
                || DelFlagEnum.DEL.getNo().equals(user.getDelFlag())) {
            return null;
        }
        long roleId = user.getRoleId();

        // 2、根据角色,获取用户角色资源权限 sys_tr_role_data_authority
        RoleDataAuthorityDto rdahDto = new RoleDataAuthorityDto();
        rdahDto.setResourcesCode(resourcesCode);
        rdahDto.setRoleId(roleId);
        rdahDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
        rdahDto.setOrders("create_time desc");
        List<RoleDataAuthority> rdahList = roleDataAuthorityMapper.selectListByDto(rdahDto);
        if (null == rdahList || rdahList.size() == 0) {
            return null;
        }

        // 用户项目组Map
        RoleDataAuthority rdah = rdahList.get(0);
        if (DataAuthorityEnums.DATA_AUTHORITY_99.getNo().equals(rdah.getAuthorityValue())) {
            // 拥有全部权限
            map.put("shiro", SHIRO_ALL);
            return map;
        } else if (DataAuthorityEnums.DATA_AUTHORITY_00.getNo().equals(rdah.getAuthorityValue())) {
            // 无权限
            return null;
        } else if (DataAuthorityEnums.DATA_AUTHORITY_02.getNo().equals(rdah.getAuthorityValue())) {
            // 3、根据userId,获取员工角色对应的权限 sys_tm_role
            // 3.1、角色不存在或被删除,返回无权限
            Role role = roleMapper.selectById(roleId);
            if (null == role || DelFlagEnum.DEL.getNo().equals(role.getDelFlag())) {
                return null;
            }

            SalesGroupUserDto salesGroupUserDto = new SalesGroupUserDto();
            salesGroupUserDto.setUserId(userId);
            salesGroupUserDto.setStatus("0");
            List<SalesGroupUser> salesGroupUserList = salesGroupUserMapper.selectListByDto(salesGroupUserDto);
            if (null == salesGroupUserList || salesGroupUserList.size() == 0)
                return null;
            // 销售组Map
            List<SalesGroup> salesGroups = new ArrayList<SalesGroup>();
            for (SalesGroupUser salesGroupUser : salesGroupUserList) {
                SalesGroup salesGroup = salesGroupMapper.selectById(salesGroupUser.getSalesGroupId());
                if (null == salesGroup)
                    continue;
                salesGroups.add(salesGroup);
            }
            map.put("salesGroups", salesGroups);
        }
        return map;
    }
}
